using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Watchfire.AppScan;
using Watchfire.AppScan.Plugins;
using Watchfire.AppScan.Results;
using Watchfire.AppScan.Diagnostics;

namespace Watchfire.DefectLogger
{
	public abstract class DefectLoggerPluginBase : IAppScanPlugin
	{
		#region Members
		private IAppScan _appScan = null;
		private DefectSystemConfig _defectSystemConfig = new DefectSystemConfig();
		#endregion

		#region Properties

		public DefectSystemConfig Config
		{
			get { return _defectSystemConfig; }
		}

		public abstract IDefectTrackingSystem DefectTrackingSystem
		{
			get;
		}
		protected abstract string RegDefectLoggerPlugin
		{
			get;
		}
		protected abstract string RegXmlConfig
		{
			get;
		}
		protected abstract ConnectionForm ConnForm
		{
			get;
		}

		protected abstract string ContextMenuText
		{
			get;
		}

		protected abstract string PluginMenuText
		{
			get;
		}

		#endregion


		/// <summary>
		/// CTor
		/// </summary>
		/// <param name="regKeyName">shortname for registry key for plugin registry storage</param>
		/// <param name="regValueName">name for string value</param>
		public DefectLoggerPluginBase()
		{
			// Get the AppScan Instance
			_appScan = AppScanFactory.CreateInstance();

			// Load the config from the registry, if it exists there
			string storedConfig = PluginRegistry.Read(_appScan.RegistryPath, RegDefectLoggerPlugin, RegXmlConfig);
			if (storedConfig != null && storedConfig.Length > 0)
			{
				_defectSystemConfig = DefectSystemConfig.FromXml(storedConfig);
			}
		}

        /// <summary>
        /// Returns a formatted name for the issue entity
        /// </summary>
        /// <param name="entity">the entity</param>
        /// <returns>formatted string</returns>
		public static string GetEntityDesc(IEntity entity)
		{
			if (entity.Type == EntityType.Page)
				return entity.Url.Path;
			else
				return entity.Url.Path + " (" + entity.Type.ToString() + " " + entity.Name + ")";
		}

        /// <summary>
        /// Shows the configuration dialog
        /// </summary>
        /// <param name="connForm">the user control for the connection parameters</param>
        /// <param name="sender">event sender</param>
        /// <param name="e">event</param>
		public void ShowConfigDialog(object sender, EventArgs e)
		{
            try
            {
                DefectSystemConfigForm configForm = new DefectSystemConfigForm(ConnForm, this);
                configForm.Show();
            }
            catch (Exception ex)
            {
				_appScan.Debug.Logger.Log(ex.ToString());
            }
		}

		public void LogIssue(object sender, EventArgs e)
		{
            try
            {
                // TODO: Make this work on individual issues too.
                IssueSelector selectorForm = new IssueSelector(_appScan, ((e as PluginEventEventArgs).Selected as IIssueType));
                selectorForm.ShowDialog();
                // If no issue was selected, exit.
                if (selectorForm.SelectedIssue == null)
                    return;

                new LogDefectForm(this, selectorForm.SelectedIssue, selectorForm.Top, selectorForm.Left).ShowDialog();
            }
            catch (Exception ex)
            {
				_appScan.Debug.Logger.Log(ex.ToString());
            }
		}

		public void SaveConfig(DefectSystemConfig config)
		{
			// Keep the config in a member
			_defectSystemConfig = config;

			// Store it in the registry as one XML blob
			PluginRegistry.WriteSettings(_appScan.RegistryPath, RegDefectLoggerPlugin, RegXmlConfig, _defectSystemConfig.ToXml());
		}

		#region IAppScanPlugin Members

		public PluginItem ContextApplicationData
		{
			get { return null; }
		}

		public PluginItem ContextIssue
		{
			get { return new PluginItem(ContextMenuText, new PluginEventHandler(LogIssue)); }
		}

		public PluginItem ContextMenu
		{
			get { return new PluginItem(PluginMenuText, new PluginEventHandler(ShowConfigDialog)); }
		}

		public PluginItem ContextRemediation
		{
			get { return null; }
		}

		public PluginItem ContextUrlTree
		{
			get { return null; }
		}

		#endregion
	}
}
